//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_chat_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/chat_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_chat"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_chat_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectChatApiImpl) UpdateGroupMember(ctx context.Context, req *project_chat_api.UpdateGroupMemberRequest) (*project_chat_api.UpdateGroupMemberResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_chat_api.UpdateGroupMemberResponse{
			Code:   project_chat_api.UpdateGroupMemberResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_chat_api.UpdateGroupMemberResponse{
			Code:   project_chat_api.UpdateGroupMemberResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_chat_api.UpdateGroupMemberResponse{
			Code:   project_chat_api.UpdateGroupMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	groupItem, err := chat_dao.GroupDao.Get(ctx, req.ProjectId, req.ChatGroupId)
	if err != nil {
		return &project_chat_api.UpdateGroupMemberResponse{
			Code:   project_chat_api.UpdateGroupMemberResponse_CODE_NO_CHAT_GROUP,
			ErrMsg: "沟通群不存在",
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(groupItem, sessionItem.UserId, projectItem, roleItem)
	if !userPerm.CanUpdate {
		return &project_chat_api.UpdateGroupMemberResponse{
			Code:   project_chat_api.UpdateGroupMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查目标成员是否存在
	newMemberUserIdMap := map[string]bool{}
	for _, memberUserId := range req.MemberUserIdList {
		newMemberUserIdMap[memberUserId] = true
	}
	exist, err := project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, groupItem.OwnerUserId)
	if err != nil {
		return nil, err
	}
	if exist {
		newMemberUserIdMap[groupItem.OwnerUserId] = true
	}
	for memberUserId := range newMemberUserIdMap {
		exist, err := project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, memberUserId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_chat_api.UpdateGroupMemberResponse{
				Code:   project_chat_api.UpdateGroupMemberResponse_CODE_NO_MEMBER,
				ErrMsg: "项目成员不存在",
			}, nil
		}
	}
	//获取老成员
	oldMemberUserIdMap := map[string]bool{}
	memberItemList, err := chat_dao.GroupMemberDao.ListMember(ctx, req.ProjectId, req.ChatGroupId)
	if err != nil {
		return nil, err
	}
	for _, memberItem := range memberItemList {
		oldMemberUserIdMap[memberItem.UserId] = true
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//新增新用户
		for newMemberUserId := range newMemberUserIdMap {
			_, ok := oldMemberUserIdMap[newMemberUserId]
			if !ok {
				err = chat_dao.GroupMemberDao.Insert(sessCtx, &chat_dao.MemberDbItem{
					ProjectId:   req.ProjectId,
					ChatGroupId: req.ChatGroupId,
					UserId:      newMemberUserId,
					UnreadCount: 0,
					LastMsgTime: nowTime,
					JoinTime:    nowTime,
				})
				if err != nil {
					return nil, err
				}
			}
		}
		//移除老用户
		for oldMemberUserId := range oldMemberUserIdMap {
			_, ok := newMemberUserIdMap[oldMemberUserId]
			if !ok {
				err = chat_dao.GroupMemberDao.Remove(sessCtx, req.ProjectId, req.ChatGroupId, oldMemberUserId)
				if err != nil {
					return nil, err
				}
			}
		}
		return &project_chat_api.UpdateGroupMemberResponse{
			Code: project_chat_api.UpdateGroupMemberResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	for newMemberUserId := range newMemberUserIdMap {
		go api_common.SendNoticeToUser(context.Background(), newMemberUserId, &notices_chat.UpdateGroupMemberNotice{
			ProjectId:   req.ProjectId,
			ChatGroupId: req.ChatGroupId,
		})
	}
	for oldMemberUserId := range oldMemberUserIdMap {
		_, ok := newMemberUserIdMap[oldMemberUserId]
		if !ok {
			go api_common.SendNoticeToUser(context.Background(), oldMemberUserId, &notices_chat.LeaveGroupNotice{
				ProjectId:   req.ProjectId,
				ChatGroupId: req.ChatGroupId,
			})
		}
	}
	return ret.(*project_chat_api.UpdateGroupMemberResponse), nil
}

func (apiImpl *ProjectChatApiImpl) LeaveGroup(ctx context.Context, req *project_chat_api.LeaveGroupRequest) (*project_chat_api.LeaveGroupResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_chat_api.LeaveGroupResponse{
			Code:   project_chat_api.LeaveGroupResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_chat_api.LeaveGroupResponse{
			Code:   project_chat_api.LeaveGroupResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_chat_api.LeaveGroupResponse{
			Code:   project_chat_api.LeaveGroupResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	groupItem, err := chat_dao.GroupDao.Get(ctx, req.ProjectId, req.ChatGroupId)
	if err != nil {
		return &project_chat_api.LeaveGroupResponse{
			Code:   project_chat_api.LeaveGroupResponse_CODE_NO_CHAT_GROUP,
			ErrMsg: "沟通群不存在",
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(groupItem, sessionItem.UserId, projectItem, roleItem)
	if !userPerm.CanLeave {
		return &project_chat_api.LeaveGroupResponse{
			Code:   project_chat_api.LeaveGroupResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = chat_dao.GroupMemberDao.Remove(sessCtx, req.ProjectId, req.ChatGroupId, sessionItem.UserId)
		if err != nil {
			return nil, err
		}
		return &project_chat_api.LeaveGroupResponse{
			Code: project_chat_api.LeaveGroupResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	memberItemList, err := chat_dao.GroupMemberDao.ListMember(ctx, req.ProjectId, req.ChatGroupId)
	if err == nil {
		for _, memberItem := range memberItemList {
			go api_common.SendNoticeToUser(context.Background(), memberItem.UserId, &notices_chat.UpdateGroupMemberNotice{
				ProjectId:   req.ProjectId,
				ChatGroupId: req.ChatGroupId,
			})
		}
	}
	return ret.(*project_chat_api.LeaveGroupResponse), nil
}

func (apiImpl *ProjectChatApiImpl) ChangeGroupOwner(ctx context.Context, req *project_chat_api.ChangeGroupOwnerRequest) (*project_chat_api.ChangeGroupOwnerResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code:   project_chat_api.ChangeGroupOwnerResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code:   project_chat_api.ChangeGroupOwnerResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code:   project_chat_api.ChangeGroupOwnerResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	exist, err := project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, req.TargetMemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code:   project_chat_api.ChangeGroupOwnerResponse_CODE_NO_MEMBER,
			ErrMsg: "项目成员不存在",
		}, nil
	}

	groupItem, err := chat_dao.GroupDao.Get(ctx, req.ProjectId, req.ChatGroupId)
	if err != nil {
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code:   project_chat_api.ChangeGroupOwnerResponse_CODE_NO_CHAT_GROUP,
			ErrMsg: "沟通群不存在",
		}, nil
	}
	if groupItem.OwnerUserId == req.TargetMemberUserId {
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code: project_chat_api.ChangeGroupOwnerResponse_CODE_OK,
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(groupItem, sessionItem.UserId, projectItem, roleItem)
	if !userPerm.CanChangeOwner {
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code:   project_chat_api.ChangeGroupOwnerResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//新增成员
		exist, err = chat_dao.GroupMemberDao.Exist(sessCtx, req.ProjectId, req.ChatGroupId, req.TargetMemberUserId)
		if err != nil {
			return nil, err
		}
		if !exist {
			err = chat_dao.GroupMemberDao.Insert(sessCtx, &chat_dao.MemberDbItem{
				ProjectId:   req.ProjectId,
				ChatGroupId: req.ChatGroupId,
				UserId:      req.TargetMemberUserId,
				UnreadCount: 0,
				LastMsgTime: nowTime,
				JoinTime:    nowTime,
			})
			if err != nil {
				return nil, err
			}
		}
		//删除老成员
		err = chat_dao.GroupMemberDao.Remove(sessCtx, req.ProjectId, req.ChatGroupId, groupItem.OwnerUserId)
		if err != nil {
			return nil, err
		}
		//更新owner
		err = chat_dao.GroupDao.UpdateOwnerUserId(sessCtx, req.ProjectId, req.ChatGroupId, req.TargetMemberUserId)
		if err != nil {
			return nil, err
		}
		return &project_chat_api.ChangeGroupOwnerResponse{
			Code: project_chat_api.ChangeGroupOwnerResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	memberItemList, err := chat_dao.GroupMemberDao.ListMember(ctx, req.ProjectId, req.ChatGroupId)
	if err == nil {
		for _, memberItem := range memberItemList {
			go api_common.SendNoticeToUser(context.Background(), memberItem.UserId, &notices_chat.UpdateGroupNotice{
				ProjectId:   req.ProjectId,
				ChatGroupId: req.ChatGroupId,
			})
		}
	}
	return ret.(*project_chat_api.ChangeGroupOwnerResponse), nil
}

func (apiImpl *ProjectChatApiImpl) ListGroupMember(ctx context.Context, req *project_chat_api.ListGroupMemberRequest) (*project_chat_api.ListGroupMemberResponse, error) {
	emptyList := []*project_chat_api.ChatGroupMemberInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_chat_api.ListGroupMemberResponse{
			Code:       project_chat_api.ListGroupMemberResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			MemberList: emptyList,
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_chat_api.ListGroupMemberResponse{
			Code:       project_chat_api.ListGroupMemberResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			MemberList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_chat_api.ListGroupMemberResponse{
			Code:       project_chat_api.ListGroupMemberResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			MemberList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	exist, err := chat_dao.GroupDao.Exist(ctx, req.ProjectId, req.ChatGroupId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_chat_api.ListGroupMemberResponse{
			Code:       project_chat_api.ListGroupMemberResponse_CODE_NO_CHAT_GROUP,
			ErrMsg:     "沟通群不存在",
			MemberList: emptyList,
		}, nil
	}

	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		exist, err := chat_dao.GroupMemberDao.Exist(ctx, req.ProjectId, req.ChatGroupId, sessionItem.UserId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_chat_api.ListGroupMemberResponse{
				Code:       project_chat_api.ListGroupMemberResponse_CODE_NO_PERMISSION,
				ErrMsg:     "没有权限",
				MemberList: emptyList,
			}, nil
		}
	}

	memberItemList, err := chat_dao.GroupMemberDao.ListMember(ctx, req.ProjectId, req.ChatGroupId)
	if err != nil {
		return nil, err
	}
	//获取用户信息
	userIdList := []string{}
	for _, memberItem := range memberItemList {
		userIdList = append(userIdList, memberItem.UserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	memberInfoList := []*project_chat_api.ChatGroupMemberInfo{}
	for _, memberItem := range memberItemList {
		memberInfo := &project_chat_api.ChatGroupMemberInfo{
			MemberUserId: memberItem.UserId,
			ChatGroupId:  memberItem.ChatGroupId,
		}
		userItem, ok := userItemMap[memberItem.UserId]
		if ok {
			memberInfo.MemberDisplayName = userItem.BasicInfo.DisplayName
			memberInfo.MemberLogoUri = userItem.BasicInfo.LogoUri
		}
		memberInfoList = append(memberInfoList, memberInfo)
	}

	return &project_chat_api.ListGroupMemberResponse{
		Code:       project_chat_api.ListGroupMemberResponse_CODE_OK,
		MemberList: memberInfoList,
	}, nil
}

func (apiImpl *ProjectChatApiImpl) ListAllGroupMember(ctx context.Context, req *project_chat_api.ListAllGroupMemberRequest) (*project_chat_api.ListAllGroupMemberResponse, error) {
	emptyList := []*project_chat_api.ChatGroupMemberInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_chat_api.ListAllGroupMemberResponse{
			Code:       project_chat_api.ListAllGroupMemberResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			MemberList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_chat_api.ListAllGroupMemberResponse{
			Code:       project_chat_api.ListAllGroupMemberResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			MemberList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_chat_api.ListAllGroupMemberResponse{
			Code:       project_chat_api.ListAllGroupMemberResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			MemberList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	memberItemList, err := chat_dao.GroupMemberDao.ListChatGroup(ctx, req.ProjectId, sessionItem.UserId, "")
	if err != nil {
		return nil, err
	}
	chatGroupIdList := []string{}
	for _, memberItem := range memberItemList {
		chatGroupIdList = append(chatGroupIdList, memberItem.ChatGroupId)
	}

	memberItemList, err = chat_dao.GroupMemberDao.ListMemberByGroupList(ctx, req.ProjectId, chatGroupIdList)
	if err != nil {
		return nil, err
	}

	//获取用户信息
	userIdList := []string{}
	for _, memberItem := range memberItemList {
		userIdList = append(userIdList, memberItem.UserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	memberInfoList := []*project_chat_api.ChatGroupMemberInfo{}
	for _, memberItem := range memberItemList {
		memberInfo := &project_chat_api.ChatGroupMemberInfo{
			MemberUserId: memberItem.UserId,
			ChatGroupId:  memberItem.ChatGroupId,
		}
		userItem, ok := userItemMap[memberItem.UserId]
		if ok {
			memberInfo.MemberDisplayName = userItem.BasicInfo.DisplayName
			memberInfo.MemberLogoUri = userItem.BasicInfo.LogoUri
		}
		memberInfoList = append(memberInfoList, memberInfo)
	}

	return &project_chat_api.ListAllGroupMemberResponse{
		Code:       project_chat_api.ListAllGroupMemberResponse_CODE_OK,
		MemberList: memberInfoList,
	}, nil
}
